

from BaseHTTPServer import HTTPServer
from SocketServer import ThreadingMixIn
class ThreadedHTTPServer (ThreadingMixIn, HTTPServer):
  pass
  allow_reuse_address = True  # need this?
#del HTTPServer, ThreadingMixIn
del ThreadingMixIn


from BaseHTTPServer import BaseHTTPRequestHandler
class MyHandler (BaseHTTPRequestHandler):
  protocol_version = "HTTP/1.1"
  def do_GET (self):
    # Just call back to the server.
    # I don't know why there's this separation between the 'server' and the 'handler'.
    # It's a pain in the ass.
    self.server.handle(self)
  # Similar to above, but just return the header
  def do_HEAD (self):
    self.server.handle(self, headeronly=True)
del BaseHTTPRequestHandler

"""
class MyServer_threaded(ThreadedHTTPServer):
  def __init__ (self, port, root_handler):
    import threading

    self.root_handler = root_handler

    ThreadedHTTPServer.__init__(self, ('',port),MyHandler)
    server_thread = threading.Thread(target=self.serve_forever)
    server_thread.setDaemon(True)
    server_thread.start()

  def handle(self, h):
    self.root_handler.handle(h, h.path)
"""

class MyServer_threaded2(ThreadedHTTPServer):
  def __init__ (self, port, root_handler):
    self.root_handler = root_handler
    ThreadedHTTPServer.__init__(self, ('',port),MyHandler)

  def handle(self, h, *args, **kwargs):
    self.root_handler.handle(h, h.path, *args, **kwargs)

"""
class MyServer_nothread(HTTPServer):
  def __init__ (self, port, root_handler):
    from BaseHTTPServer import HTTPServer
    self.root_handler = root_handler
    HTTPServer.__init__(self, ('',port),MyHandler)

  def handle(self, h):
    self.root_handler.handle(h, h.path)

del HTTPServer
"""

from pygeode.server.daemon import Daemon
class HTTPDaemon(Daemon):
  def __init__ (self, port, root_handler):
    from pygeode.server.daemon import Daemon
    from pygeode import libpath
    prefix=libpath+'/server/httpd%i'%port
    Daemon.__init__(self, prefix+'.pid', stdout=prefix+'.stdout', stderr=prefix+'.stderr')
    self.port = port
    self.root_handler = root_handler

  # What gets run when the daemon is started
  # (the httpserver process)
  def run(self):
#    MyServer_nothread(self.port, self.root_handler).serve_forever()
    MyServer_threaded2(self.port, self.root_handler).serve_forever()
    
del Daemon



class Dir:
  def __init__(self):
    self.nodes = {}

  def dir_header (self, h, relpath):
    h.wfile.write("<h1>Index of %s</h1><hr><br>\n"%h.path)

  def dir_footer (self, h, relpath):
    h.wfile.write("<br><hr><i>Virtual webfolder generated by PyGeode</i>\n")

  def handle (self, h, relpath, headeronly=False):
#    print "dir handler:", relpath

    # Full path
    path = h.path
    if not path.endswith('/'): path += '/'

    # Base case: directory listing
    if relpath == "": relpath = "/"
    if relpath == "/":
      h.send_response(200)
      h.send_header ("Content-Type", "text/html; charset=UTF-8")
      h.send_header ("Connection", "close")
      h.end_headers()

      if headeronly: return

      self.dir_header (h, relpath)
      # Sort the file names
      names = sorted(self.nodes.iterkeys())
      for name in names:
        node = self.nodes[name]
        # Check for subdirectories? (append a trailing '/' to make them easier to see)
        if isinstance(node,Dir): name = name + "/"
        h.wfile.write("<a href='%s%s'>%s</a><br>\n"%(path,name,name))
      if len(self.nodes) == 0:
        h.wfile.write("<h1>(Empty Directory)</h1>\n")
      self.dir_footer (h, relpath)
    # Otherwise, need to delegate to whatever node was requested
    else:
#      assert len(relpath) > 0 and relpath[0] == "/", "malformed directory?"
      if len(relpath) == 0 or relpath[0] != "/":
        h.send_error(404)#, "error parsing '%s'"%relpath)
        return
      # Split (if a directory)

      # Remove the leading '/'
      # We should have always had the /, the if statement is just for completeness
      if relpath.startswith('/'): relpath = relpath[1:]

      name_and_path = relpath.split('/', 1)
      if len(name_and_path) == 1: name_and_path += ['']
      name, path = name_and_path

      # Check that we have this name in our directory space
      if name not in self.nodes:
        h.send_error(404)#, "'%s' not in %s - relpath='%s'"%(name,self.nodes,relpath))
        return

      # Call the sub-node handler
      node = self.nodes[name]
      node.handle (h, '/'+path, headeronly=headeronly)

  def add (self, name, node):
    self.nodes[name] = node

